package local;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;

import java.io.FileOutputStream;
import java.io.IOException;

import static org.objectweb.asm.Opcodes.*;

public class GenerateLicenseCheckerClass {

    public static void main(String[] args) throws IOException {
        byte[] classBytes = generateLicenseCheckerClass();
        // 输出到 com/fr/web/core/LicenseChecker.class（需手动创建目录）
        try (FileOutputStream fos = new FileOutputStream("LicenseChecker.class")) {
            fos.write(classBytes);
        }
        System.out.println("LicenseChecker.class 已生成（请放入 com/fr/web/core/ 目录）");
    }

    public static byte[] generateLicenseCheckerClass() {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
        cw.visit(V1_8, ACC_PUBLIC, "com/fr/web/core/LicenseChecker", null, "java/lang/Object", null);

        MethodVisitor mv = cw.visitMethod(
                ACC_PUBLIC | ACC_STATIC,
                "checkLicense",
                "()V",
                null,
                new String[]{"java/lang/Exception"}
        );
        mv.visitCode();

        // Labels
        Label label125 = new Label();
        Label label18 = new Label();
        Label afterIf1 = new Label();
        Label ifEq85 = new Label();
        Label ifEq102 = new Label();
        Label goto109 = new Label();

        // 0: iconst_1
        mv.visitInsn(ICONST_1);
        // 1: ifeq 125
        mv.visitJumpInsn(IFEQ, label125);

        // 4: System.currentTimeMillis()
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
        // 7: ldc2_w 10000000L
        mv.visitLdcInsn(10000000L);
        // 10: lcmp
        mv.visitInsn(LCMP);
        // 11: ifgt 18
        mv.visitJumpInsn(IFGT, label18);

        // 14: iconst_0
        mv.visitInsn(ICONST_0);
        mv.visitJumpInsn(GOTO, afterIf1);

        // 18: iconst_1
        mv.visitLabel(label18);
        mv.visitInsn(ICONST_1);

        mv.visitLabel(afterIf1);
        // 19: istore_2
        mv.visitVarInsn(ISTORE, 2);

        // 20: iload_2
        mv.visitVarInsn(ILOAD, 2);
        // 21: ifeq 125
        mv.visitJumpInsn(IFEQ, label125);

        // 24: new FRException
        mv.visitTypeInsn(NEW, "com/fr/stable/FRException");
        mv.visitInsn(DUP);
        mv.visitIntInsn(SIPUSH, 2102);
        mv.visitMethodInsn(INVOKESTATIC, "com/fr/locale/InterProviderFactory", "getProvider", "()Lcom/fr/locale/InterProvider;", false);
        mv.visitLdcInsn("Fine-Core_Base_Need_Purchase_Info");
        mv.visitMethodInsn(INVOKEINTERFACE, "com/fr/locale/InterProvider", "getLocText", "(Ljava/lang/String;)Ljava/lang/String;", true);
        mv.visitLdcInsn("Fine-Core_Base_Need_Purchase_Info");
        mv.visitMethodInsn(INVOKESPECIAL, "com/fr/stable/FRException", "<init>", "(ILjava/lang/String;Ljava/lang/String;)V", false);
        // 48: astore 4
        mv.visitVarInsn(ASTORE, 4);

        // 50: get PluginModule.ExtraCore
        mv.visitFieldInsn(GETSTATIC, "com/fr/plugin/injectable/PluginModule", "ExtraCore", "Lcom/fr/plugin/injectable/PluginModule;");
        mv.visitMethodInsn(INVOKESTATIC, "com/fr/plugin/injectable/PluginModule", "getAgent", "(Lcom/fr/plugin/injectable/PluginModule;)Ljava/lang/Object;", false);
        mv.visitTypeInsn(CHECKCAST, "com/fr/stable/plugin/ExtraClassManagerProvider");
        // 59: astore 5
        mv.visitVarInsn(ASTORE, 5);

        // 61: aconst_null
        mv.visitInsn(ACONST_NULL);
        // 62: astore 6
        mv.visitVarInsn(ASTORE, 6);

        // 64: aload 5
        mv.visitVarInsn(ALOAD, 5);
        // 66: aconst_null
        mv.visitInsn(ACONST_NULL);
        // 67: if_acmpeq 85
        mv.visitJumpInsn(IF_ACMPEQ, ifEq85);

        // 70: aload 5
        mv.visitVarInsn(ALOAD, 5);
        mv.visitLdcInsn("UnregisteredPageProcessor");
        // 注意：你字节码中调用的是 PluginBeanFactory.getSingle，但对象是 ExtraClassManagerProvider
        // 根据常量池 #355 描述，接口方法属于哪个类型？
        // 你写的是：invokeinterface #355, 2 -> 方法名 getSingle
        // 但 receiver 是 ExtraClassManagerProvider（#328），所以应调用它的 getSingle
        // 然而你注释写的是 PluginBeanFactory —— 这里以字节码实际 receiver 为准
        mv.visitMethodInsn(INVOKEINTERFACE, "com/fr/stable/plugin/ExtraClassManagerProvider", "getSingle", "(Ljava/lang/String;)Lcom/fr/stable/fun/mark/Immutable;", true);
        mv.visitTypeInsn(CHECKCAST, "com/fr/stable/fun/UnregisteredPageProcessor");
        // 83: astore 6
        mv.visitVarInsn(ASTORE, 6);

        mv.visitLabel(ifEq85);
        // 85: aload 6
        mv.visitVarInsn(ALOAD, 6);
        // 87: aconst_null
        mv.visitInsn(ACONST_NULL);
        // 88: if_acmpeq 102
        mv.visitJumpInsn(IF_ACMPEQ, ifEq102);

        // 91: aload 6
        mv.visitVarInsn(ALOAD, 6);
        mv.visitMethodInsn(INVOKEINTERFACE, "com/fr/stable/fun/UnregisteredPageProcessor", "createWeblet", "()Lcom/fr/stable/web/Weblet;", true);
        // 98: astore_3
        mv.visitVarInsn(ASTORE, 3);
        mv.visitJumpInsn(GOTO, goto109);

        mv.visitLabel(ifEq102);
        // 102: ldc "/com/fr/web/tpl/lic.frm"
        mv.visitLdcInsn("/com/fr/web/tpl/lic.frm");
        mv.visitMethodInsn(INVOKESTATIC, "com/fr/web/factory/WebletFactory", "createEmbeddedWeblet", "(Ljava/lang/String;)Lcom/fr/stable/web/Weblet;", false);
        // 108: astore_3
        mv.visitVarInsn(ASTORE, 3);

        mv.visitLabel(goto109);
        // 109: aload 4
        mv.visitVarInsn(ALOAD, 4);
        mv.visitTypeInsn(NEW, "com/fr/web/core/DefaultHandlerMethod");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKESPECIAL, "com/fr/web/core/DefaultHandlerMethod", "<init>", "(Lcom/fr/stable/web/Weblet;)V", false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "com/fr/stable/FRException", "setHandlerMethod", "(Lcom/fr/stable/HandlerMethod;)V", false);
        // 122: aload 4
        mv.visitVarInsn(ALOAD, 4);
        // 124: athrow
        mv.visitInsn(ATHROW);

        mv.visitLabel(label125);
        // 125: return
        mv.visitInsn(RETURN);

        mv.visitMaxs(0, 0); // auto-computed
        mv.visitEnd();

        cw.visitEnd();
        return cw.toByteArray();
    }
}